/* Copyright (c) 2004-2008, Andriy Nikolov
 * All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package org.processmining.importing.email;

import org.kxml2.io.*;
import org.kxml2.kdom.*;
import org.processmining.framework.log.*;
import org.xmlpull.v1.*;
import org.processmining.email.*;
import java.io.*;
import java.util.*;
import java.text.*;

/**
 * @author not attributable
 * @version 1.0
 */
public class ProcessLogPreferencesReader {


  static ProcessLog processLog;
  static String value;
  static String id;
  static String address;
  static ProcessCase curCase;
  static ProcessTaskType curTask;
  static ProcessEventType curEvent;

  static boolean casesStarted = false;
  static boolean caseStarted = false;
  static boolean tasksStarted = false;
  static boolean taskStarted = false;
  static boolean eventsStarted = false;
  static boolean charactersStarted = false;
  static String currentElement;

  static final int ELEMENT_NONE = 0;
  static final int ELEMENT_FROM = 1;
  static final int ELEMENT_TO = 2;
  static final int ELEMENT_CC = 3;
  static final int ELEMENT_BCC = 4;
  static final int ELEMENT_SUBJECT = 5;
  static final int ELEMENT_CASE = 6;
  static final int ELEMENT_TASK = 7;
  static final int ELEMENT_PHASE = 8;


  XmlPullParser parser;
  XmlPullParserFactory factory;

  public void setProcessLog(ProcessLog log) {
    processLog = log;
  }

  private void jbInit(InputStream input) throws Exception {
        System.setProperty("org.xmlpull.v1.XmlPullParserFactory", "org.kxml2.io.KXmlParser");
        factory = XmlPullParserFactory.newInstance(System.getProperty("org.xmlpull.v1.XmlPullParserFactory"), null);
        factory.setNamespaceAware(true);
        parser = factory.newPullParser();
        parser.setInput(input, "UTF-8");
  }

  public ProcessLogPreferencesReader(InputStream input) {
    try {
      jbInit(input);
    } catch (Exception exception) {
      exception.printStackTrace();
    }

  }

  public ProcessLogPreferencesReader(InputStream input, ProcessLog log) {
    this.processLog = log;
    try {
      jbInit(input);
    } catch (Exception exception) {
      exception.printStackTrace();
    }
  }

  public void parse() {
    int eventType;
    try {
      eventType = parser.getEventType();
      do {
        switch(eventType) {
          case XmlPullParser.START_DOCUMENT:
            startDocument();
            break;
          case XmlPullParser.START_TAG:
            startElement();
            break;
          case XmlPullParser.TEXT:
            processText();
            break;
          case XmlPullParser.END_TAG:
            endElement();
        }
        eventType = parser.next();
      } while(eventType!=XmlPullParser.END_DOCUMENT);
    } catch (XmlPullParserException xmlException) {
      xmlException.printStackTrace();
    } catch (IOException ioException) {
      ioException.printStackTrace();
    }
  }

  private void startDocument() {
  }

  private void processText() {
    int[] arrayStartAndLength = new int[2];
    char ch[];
    int start, length;
    ch = parser.getTextCharacters(arrayStartAndLength);
    start = arrayStartAndLength[0];
    length = arrayStartAndLength[1];

    if (!charactersStarted) {
      value = new String(ch, start, length);
    } else {
      value = value + new String(ch, start, length);
    }
    value = value.trim();
//    System.out.println("Value: "+value);
//    System.out.println("Start: "+start);
//    System.out.println("Length: "+length);

//    if((value.length()>0)&&(value.length()-start>length)) {
//      value = value.substring(start, length);
//    }
    charactersStarted = true;

  }

  private void startElement() {
    String localName = parser.getName();
    if(localName.equals("Cases")) {
          processLog.setCaseSourceType(Integer.parseInt(parser.getAttributeValue("", "source")));
          processLog.setPartialCoincidenceCasesAllowed(Boolean.valueOf(parser.getAttributeValue("", "partial")).booleanValue());
        }

        if(localName.equals("Tasks")) {
          processLog.setTaskSourceType(Integer.parseInt(parser.getAttributeValue("", "source")));
          processLog.setPartialCoincidenceTasksAllowed(Boolean.valueOf(parser.getAttributeValue("", "partial")).booleanValue());
        }

        if(localName.equals("Events")) {
          processLog.setEventSourceType(Integer.parseInt(parser.getAttributeValue("", "source")));
          processLog.setHasToAssignMissingEvents(Boolean.valueOf(parser.getAttributeValue("", "missing")).booleanValue());
          processLog.setHasToSaveMessageData(Boolean.valueOf(parser.getAttributeValue("", "saveMessageData")).booleanValue());
          processLog.setIgnoreReplies(Boolean.valueOf(parser.getAttributeValue("", "replies")).booleanValue());
        }

        if(localName.equals("Case")) {
          caseStarted = true;
          curCase = processLog.addCase(parser.getAttributeValue("", "name"));
        }

        if(localName.equals("Task")) {
          taskStarted = true;
          curTask = processLog.addTaskType(parser.getAttributeValue("", "name"));
        }

        if(localName.equals("Event")) {
          processLog.addEventType(parser.getAttributeValue("", "name"), parser.getAttributeValue("", "alias"));
        }
    charactersStarted = false;
  }

  private void endElement() {
    if(currentElement.equals("Alias")) {
      if(caseStarted) {
        curCase.addAlias(value);
      }
      if(taskStarted) {
        curTask.addAlias(value);
      }
    }

    if(currentElement.equals("Case")) {
      caseStarted = false;
    }

    if(currentElement.equals("Task")) {
      taskStarted = false;
    }
  }

}
